package cn.goour.web.sys.entity.graphql

import cn.goour.web.sys.entity.Admin
import com.alibaba.fastjson.JSONObject
import graphql.GraphQL
import graphql.Scalars
import graphql.schema.*
import graphql.schema.GraphQLArgument.newArgument
import graphql.schema.GraphQLFieldDefinition.newFieldDefinition
import graphql.schema.GraphQLObjectType.newObject
import java.lang.reflect.Field
import java.math.BigDecimal
import java.math.BigInteger


class GraphQLTools {
    companion object {
        private val objMap = HashMap<String, GraphQLObjectType>()

        /**
         * 与实体类关联的类
         */
        fun getObjectType(clazz: Class<*>): GraphQLObjectType {
            val name = clazz.simpleName
            if (objMap.containsKey(name)) {
                return objMap[name]!!
            }
            val fileds = clazz.declaredFields
            val objectType = newObject().name(name)
            fileds.forEach {
                val type = getType(it)
                objectType.field(newFieldDefinition().name(it.name).type(type).build())
            }
            val result = objectType.build()
            objMap[name] = result
            return result
        }

        fun getAdminField(clazz: Class<*>) = getAdminField(getObjectType(clazz))
        fun getAdminFields(clazz: Class<*>) = getAdminFields(getObjectType(clazz))

        /**
         * 一个可供查询的接口
         */
        fun getAdminField(bean: GraphQLObjectType): GraphQLFieldDefinition {
            val findforid = GraphQLFieldDefinition.newFieldDefinition().name(bean.name)
                    .argument(//这里用GraphQL些查询语句时传入的参数
                            newArgument()
                                    .name("id")//参数名为id
                                    .type(Scalars.GraphQLInt)//参数类型
                                    .build()
                    )
                    .type(bean)//绑定GraphQL的一个结构，就是上面的那段代码
                    .dataFetcher {
                        return@dataFetcher Admin()
                    }.build()
            return findforid
        }

        fun getAdminFields(bean: GraphQLObjectType): GraphQLFieldDefinition {
            val findforid = GraphQLFieldDefinition.newFieldDefinition().name("${bean.name}s")
                    .argument(//这里用GraphQL些查询语句时传入的参数
                            newArgument()
                                    .name("id")//参数名为id
                                    .type(Scalars.GraphQLInt)//参数类型
                                    .build()
                    )
                    .type(GraphQLList(bean))//绑定GraphQL的一个结构，就是上面的那段代码
                    .dataFetcher {
                        val list = arrayListOf<Admin>()
                        for (i in 1..10) {
                            list.add(Admin())
                        }
                        return@dataFetcher list
                    }.build()
            return findforid
        }

        private fun getType(field: Field): GraphQLScalarType {
            return when {
//                field.type == Int::class.java && field.name == "id" -> Scalars.GraphQLID
                field.type == Int::class.java -> Scalars.GraphQLInt
                field.type == Float::class.java -> Scalars.GraphQLFloat
                field.type == String::class.java -> Scalars.GraphQLString
                field.type == Boolean::class.java -> Scalars.GraphQLBoolean
                field.type == Long::class.java -> Scalars.GraphQLLong
                field.type == Short::class.java -> Scalars.GraphQLShort
                field.type == Byte::class.java -> Scalars.GraphQLByte
                field.type == BigInteger::class.java -> Scalars.GraphQLBigInteger
                field.type == BigDecimal::class.java -> Scalars.GraphQLBigDecimal
                field.type == Char::class.java -> Scalars.GraphQLChar
                else -> Scalars.GraphQLString
            }
        }
    }
}

fun main(args: Array<String>) {
//    val adminObj = newObject().name("admin").field(newFieldDefinition().name("id").type(Scalars.GraphQLInt).build())
    val filed = Admin::class.java.declaredFields
    val schema = GraphQLSchema.newSchema()
            .query(newObject().name("AdminSearch")
                    .field(GraphQLTools.getAdminField(Admin::class.java))//半桶水不知道怎么描述它
                    .field(GraphQLTools.getAdminFields(Admin::class.java))//半桶水不知道怎么描述它
                    .build()
            )
            .build()
    val str1 = "{Admin(id:1){id,name,username}}"
    val str2 = "{Admins(id:1){id,name,username}}"
    val hql = GraphQL(schema)
//最后就是获取结果了
    val re1 = hql.execute(str1)
    val re2 = hql.execute(str2)
    val json = JSONObject()
    json.put("b1", re1.getData<Any>())
    json.put("b2", re2.getData<Any>())
    System.out.println(json)//输出就成了json数据了：{"zy":{"id":1,"title":"服装与服饰设计","readnum":0}}
}
